// OpAnnotationDwgText.ts

import {
  Vector3,
  Font,
  Scene,
  Mesh,
  TextGeometry,
  Raycaster,
  Material,
} from "../../WebViewer/THREE/Three";
import { AnnotationMesh, OpAnnotationDwg } from "./OpAnnotationDwg";

class OpAnnotationDwgText extends OpAnnotationDwg {
  constructor(app: any) {
    super(app);
  }

  tempAnnotationPointerUp() {
    super.stopAnnotation();
  }

  createText(text: string) {
    const scene = this.app.bimViewer.getIncrementalScene();
    const font = this.app.bimViewer.getRenderContext().getWebGLFont();
    const point = new Vector3();
    const mesh = new AnnotationTextMesh({
      start: point,
      end: point,
      font,
      scene,
      lineSize: this.lineSize,
      textSize: this.textSize,
      color: this.color,
      text: text,
    });

    return mesh;
  }

  createAnnotationFromData(data: {
    ptsArr: Array<number[]>;
    lineSize: number;
    textSize: number;
    color: string;
    text: string;
  }) {
    let pointArr: Vector3[] = [];
    data.ptsArr.forEach((item: number[]) => {
      const v3 = new Vector3().fromArray(item);
      pointArr.push(v3);
    });

    const scene = this.app.bimViewer.getIncrementalScene();
    const font = this.app.bimViewer.getRenderContext().getWebGLFont();
    const mesh = new AnnotationTextMesh({
      start: pointArr[0],
      end: pointArr[0],
      font,
      scene,
      lineSize: data.lineSize,
      textSize: data.textSize,
      color: data.color,
      text: data.text,
    });

    mesh.updateDragShape(0);
    mesh.setDragHandleVisible(false);

    return mesh;
  }
}

class AnnotationTextMesh extends AnnotationMesh {
  textMesh!: Mesh;
  text: string;

  constructor(param: {
    start: Vector3;
    end: Vector3;
    font: Font;
    scene: Scene;
    lineSize: number;
    textSize: number;
    color: string;
    text: string;
  }) {
    super(param);

    this.ptsArr = [param.start.clone()];

    this.text = "";

    this._createLineTextShape(param.text);
  }

  private _createLineTextShape(text: string) {
    this.text = text;

    this.ptsArr.forEach((point) => {
      const drag = this.createDragHandle(point);
      this.dragHandleArr.push(drag);
      drag.install(this.scene);
    });

    const textGeo = new TextGeometry(text, {
      font: this.font,
      size: this.textSize,
      height: 0.001,
      curveSegments: 10,
    });
    this.textMesh = new Mesh(textGeo, this.material);

    this.scene.add(this.textMesh);
  }

  updateLineTextShape() {}

  updateDragShape(current: number) {
    this.dragHandleArr[0].setPosition(this.ptsArr[0]);

    this.textMesh.position.copy(this.ptsArr[0]);
  }

  setMeshVisible(value: boolean) {
    if (value === false) {
      this.dragHandleArr.forEach((item) => {
        item.setVisible(value);
      });
    }

    this.textMesh.visible = value;
  }

  dispose() {
    super.dispose();
    this.scene.remove(this.textMesh);
  }

  intersectObjects(_rayCaster: Raycaster) {
    let children: any = [];
    children.push(this.textMesh);

    const intersects = _rayCaster.intersectObjects(children, true);
    if (intersects.length > 0) {
      return true;
    }

    return false;
  }

  changeMeshMaterial(material: Material) {
    if (this.textMesh.material === material) {
      return;
    }

    this.textMesh.material = material;
  }

  getData() {
    let pointArr: any = [];
    this.ptsArr.forEach((item) => {
      const arr = item.toArray();
      pointArr.push(arr);
    });

    let obj = {
      ptsArr: pointArr,
      lineSize: this.lineSize,
      textSize: this.textSize,
      color: this.color,
      text: this.text,
    };

    return obj;
  }
}

export { OpAnnotationDwgText };
